//////////////////////////////////////////////////////////////////////////////////
//	 Copyright 2011 by Yosef Grabivker, ryuho@homenetworksoft.com
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//////////////////////////////////////////////////////////////////////////////////

#include <wx/wx.h>
#include "utils.h"
#include "logicmanager.h"
#include "../common/MarkupSTL.h"
#include "wirelessproghw.h"

CWirelessProgHW::CWirelessProgHW(CLinkGuard& link, const wxString& strWirelessCMDName,
								 const wxString& strWirelessInterface):CWirelessHW(link),
								 m_strWirelessCMDName(strWirelessCMDName), m_strWirelessInterface(strWirelessInterface)
{
}

CWirelessProgHW::~CWirelessProgHW(void)
{
}

std::string CWirelessProgHW::GetStats(std::string& strRawData)
{
	wxString strCMD;
	RTSTRING strData;
	long lVal(0);

	wxString strWirelessCMD = BuildWirelessCMD();

	CMarkupSTL	doc;
	doc.AddElem( "wireless" );

	//Get Connected list
	strCMD = strWirelessCMD+wxT(" status");

	int nRet(3);

	do 
	{
		strData = m_link->SendCmd( strCMD, 1000 );

	} while ( nRet-->0 && strData.empty() );

	if ( !strData.empty() )
	{
		ParseStatus(doc, WRLS_XML_TAG_STATUS, strData  );
	}
	else
	{
		//status may failed
		doc.AddChildElem( WRLS_XML_TAG_STATUS );
	}

	//Get radio
	strCMD = strWirelessCMD+wxT(" radio");
	strData = m_link->SendCmd( strCMD );
	
	if (1==sscanf(strData.c_str(),"%x", &lVal) )
	{
		doc.AddChildAttrib(WRLS_XML_ATTR_RADIO, lVal?"off":"on" );
	}

	/*
	wl noise
	wl rssi (receive signal strength)
	wl tssi (transmit signal strength)
	wl rssidump
	wl channel_qa (requires setting channel_qa_start).
	*/

	/*
	wlctl rate
	54 Mbps
	*/

	/*
	> wlctl assoc
SSID: "RND2"
Mode: Managed   RSSI: 0 dBm     noise: 0 dBm    Channel: 1
BSSID: 00:26:5A:DE:0B:E5        Capability: ESS ShortSlot
Supported Rates: [ 1(b) 2(b) 5.5(b) 6 9 11(b) 12 18 24 36 48 54 ]
	*/
/*
	> wlctl channels
1 2 3 4 5 6 7 8 9 10 11 12 13
> wlctl curpower
Power Control:           On, HW
Current channel:         1
BSS channel:             1
BSS Local Max:          63.0  dBm
BSS Local Constraint:    0.0  dB
User Target:            31.75 dBm
SROM antgain:            2G: 2.0 dB, 5G: 0.0 dB

Regulatory Limits:
CCK: 17.0   OFDM: 17.0

Board Limits:
CCK: 16.50  OFDM: 16.50

Power Target:
CCK:  3.0   OFDM:  3.0

Last est. power:        12.25 dBm
Last CCK est. power:    12.25 dBm
*/

/*
> wlctl pktcnt
Receive: good packet 193223, bad packet 0, othercast good packet 39939
Transmit: good packet 236900, bad packet 344
*/

/*
Received signal strength indication 
wlctl rssi 00:0E:35:FE:19:E7
*/

/*
pwr_percent
Get/Set power output percentage
> wlctl pwr_percent
20
*/
/*
> wlctl assoclist
assoclist 
assoclist 00:0E:35:FE:19:E7
*/

/*
wlctl txpwr [1-255] (1->1 mW, 127->42mW, 255->84mW).
*/

/*
#!/bin/sh
###############################################
#----Created by MOJSO-----Script version 2----#
###############################################
#         SIGNAL STRENGTH                         
# 0 blink   =  SNR  < 9  No signal or very weak     
# 1 blink   =  SNR 10-19                           
# 2 blinks  =  SNR 20-29                           
# 3 blinks  =  SNR 30-39                      
# 4 blinks  =  SNR 40-49                 
# 5 blinks  =  SNR 50-59                 
# 6 blinks  =  SNR 60 >   Excellent signal 
###############################################
while sleep 3; do
BLACK=`gpio enable 3 ; gpio enable 2`
S=`wl rssi` #(put mac adress if in AP mod example: S=`wl rssi 00:11:22:33:44:55` )
N=`wl noise`

SC=`expr $S - $N` 
RSC=`expr $SC / 10`
*/

	strCMD = strWirelessCMD+wxT(" rate");
	strData = m_link->SendCmd( strCMD );
	doc.AddChildAttrib(WRLS_XML_ATTR_RATE, strData.c_str() );


	//Get noise dBm
	strCMD = strWirelessCMD+wxT(" noise");
	strData = m_link->SendCmd( strCMD );
	doc.AddChildAttrib(WRLS_XML_ATTR_NOISE, strData.c_str() );

	int nNoiseLevel = atol( strData.c_str() );

	if (nNoiseLevel>0)
	{
		nNoiseLevel = 0;
	}

	//Get isup
	strCMD = strWirelessCMD+wxT(" isup");
	strData = m_link->SendCmd( strCMD );
	doc.AddChildAttrib(WRLS_XML_ATTR_ISUP, strData.c_str() );

	//Get pwr_percent
	strCMD = strWirelessCMD+wxT(" pwr_percent");
	strData = m_link->SendCmd( strCMD );
	doc.AddChildAttrib(WRLS_XML_ATTR_PWRPERC, strData.c_str() );

	//Get txpwr
	strCMD = strWirelessCMD+wxT(" txpwr");
	strData = m_link->SendCmd( strCMD );
	doc.AddChildAttrib(WRLS_XML_ATTR_TXPWR, strData.c_str() );

	//Get wepstatus
	strCMD = strWirelessCMD+wxT(" wepstatus");
	strData = m_link->SendCmd( strCMD );
	doc.AddChildAttrib(WRLS_XML_ATTR_WEPSTATUS, strData.c_str() );

	//Get wsec
	strCMD = strWirelessCMD+wxT(" wsec");
	strData = m_link->SendCmd( strCMD );
	doc.AddChildAttrib(WRLS_XML_ATTR_WSEC, strData.c_str() );

	//Get wpa_auth
	strCMD = strWirelessCMD+wxT(" wpa_auth");
	strData = m_link->SendCmd( strCMD );
	doc.AddChildAttrib(WRLS_XML_ATTR_WPA_AUTH, strData.c_str() );

	//Get Connected list
	strCMD = strWirelessCMD+wxT(" assoclist");
	strData = m_link->SendCmd( strCMD );

	if ( !strData.empty() )
	{
		ParseMACList(doc, WRLS_XML_TAG_ASSOC_LST, strData, nNoiseLevel  );
	}

	return doc.GetDoc();
}

void CWirelessProgHW::ParseMACList( CMarkupSTL& doc, const char* szTAG, const RTSTRING& strData, int nNoise) const
{
	wxString strCMD;
	RTSTRING strInfo;

	TEXTLIST lst = StrToList( wxString::FromAscii( strData.c_str()) );

	if ( !lst.empty() )
	{
		doc.AddChildElem( szTAG );
		doc.IntoElem();

		for(size_t i=0;i<lst.size();i++)
		{
			wxString strMAC = ExtractMACFromString(wxString::FromAscii( lst[i].c_str()));

			if ( !strMAC.empty() )
			{
				doc.AddChildElem( "entry",  (const char*)strMAC.ToAscii() );
				strCMD = BuildWirelessCMD()+wxT(" sta_info ");
				strCMD+=strMAC;

				/*
				rateset [ 1 2 5.5 6 9 11 12 18 24 36 48 54 ]
				idle 1 seconds
				in network 41 seconds
				state: AUTHENTICATED ASSOCIATED AUTHORIZED
				flags 0x4138: PS
				tx pkts: 66
				tx failures: 0
				rx ucast pkts: 106
				rx mcast/bcast pkts: 62
				rate of last tx pkt: 54000 kbps
				rate of last rx pkt: 1000 kbps
				*/
				strInfo = m_link->SendCmd( strCMD );

				RTSTRING str;
				long lVal;

				if ( !strInfo.empty() )
				{
					str = CLogicManager::GetStringWithPattern(strInfo, "rateset", true);
					doc.AddChildAttrib( WRLS_XML_ATTR_CLNT_RATESET, str.c_str() );

					str = CLogicManager::GetStringWithPattern(strInfo, "idle", true);
					doc.AddChildAttrib( WRLS_XML_ATTR_CLNT_IDLE, str.c_str() );

					str = CLogicManager::GetStringWithPattern(strInfo, "in network", true);
					doc.AddChildAttrib( WRLS_XML_ATTR_CLNT_INNETW, str.c_str() );

					str = CLogicManager::GetStringWithPattern(strInfo, "state:", true);
					doc.AddChildAttrib( WRLS_XML_ATTR_CLNT_STATE, str.c_str() );

					lVal = CLogicManager::ToNumberValIfLineHave(strInfo, "tx pkts:");
					doc.AddChildAttrib( WRLS_XML_ATTR_CLNT_TX, lVal );

					lVal = CLogicManager::ToNumberValIfLineHave(strInfo, "tx failures:");
					doc.AddChildAttrib( WRLS_XML_ATTR_CLNT_TXFAIL, lVal );

					lVal = CLogicManager::ToNumberValIfLineHave(strInfo, "rx ucast pkts:");
					doc.AddChildAttrib( WRLS_XML_ATTR_CLNT_RX_UCAST, lVal );

					lVal = CLogicManager::ToNumberValIfLineHave(strInfo, "rx mcast/bcast pkts:");
					doc.AddChildAttrib( WRLS_XML_ATTR_CLNT_RX_MBCAST, lVal );

					str = CLogicManager::GetStringWithPattern(strInfo, "rate of last tx pkt:", true);
					doc.AddChildAttrib( WRLS_XML_ATTR_CLNT_TX_RATE, str.c_str() );

					str = CLogicManager::GetStringWithPattern(strInfo, "rate of last rx pkt:", true);
					doc.AddChildAttrib( WRLS_XML_ATTR_CLNT_RX_RATE, str.c_str() );
				}

				strCMD = BuildWirelessCMD()+wxT(" rssi ");
				strCMD+=strMAC;
				strInfo = m_link->SendCmd( strCMD );
				int nRSSI = atol( strInfo.c_str() );

				if ( nRSSI )
				{
					int nLevel = nRSSI-nNoise;
					doc.AddChildAttrib( WRLS_XML_ATTR_CLNT_SIGN_STRNGTH, nLevel );
				}
			}
		}

		doc.OutOfElem();
	}
}

void  CWirelessProgHW::ParseStatus(class CMarkupSTL& doc, const char* szTAG, const RTSTRING& strData) const
{
	NAMEDVALS lst;
	if ( CLogicManager::ExtractPairs( ":", strData, lst ) )
	{
		doc.AddChildElem( szTAG );

		for(size_t i=0;i<lst.size();i++)
		{
			NAMEDVAL& val = lst[i];

			for(size_t j=0;j<val.strVal.size();j++)
			{
				if ( val.strVal[j]=='"' )
				{
					val.strVal.erase( val.strVal.begin()+j );
					//j=0;
				}
			}

			for(size_t k=0;k<val.strLabel.size();k++)
			{
				if ( val.strLabel[k]==' ' && k )
				{
					val.strLabel[k]='_';
				}
			}

			doc.AddChildAttrib( val.strLabel.c_str(),  val.strVal.c_str() );
		}
	}
}

wxString CWirelessProgHW::BuildWirelessCMD() const
{
	wxString strRes = m_strWirelessCMDName;

	if ( !m_strWirelessInterface.empty() )
	{
		strRes+=wxT(" -i ")+m_strWirelessInterface;
	}

	return strRes;
}


///////////////////////////////////////////////////////////////////////////////////////////////////
std::string CWirelessProgHW::GetCaps()
{
	CMarkupSTL	doc;
	doc.AddElem( WIRELESS_CAPS );

	doc.AddAttrib( GLOBAL_NAME_ATR,		"Generic Wireless" );

	return doc.GetDoc();
}

void CWirelessProgHW::SetUp(const std::string& strModemSettings)
{
}

bool CWirelessProgHW::ExecuteXML(const std::string& strModemSettings)
{
	bool bRes(false);


	return bRes;
}
